#include "perf_test.h"
void perfTest() {
    srand((unsigned)time(NULL));
    int n, nrhs;
    double gflops;
    /*
    // test 96 threads
    omp_set_num_threads(96);
    // small scale
    for (n = 100; n <= 900; n += 100) {
        //nrhs = rand() % n + 1;  // NRHS=[1,N]
        nrhs = n;
        printf("N = %d,\tNRHS=%d\n", n, nrhs);
        gflops = calGflops(n, nrhs);
        printf("  nThread:96,\tgflops=%lf\n", gflops);
    }
    // middle scale
    for (n = 1000; n <= 9000; n += 1000) {
        //nrhs = rand() % n + 1;  // NRHS=[1,N]
        nrhs = n;
        printf("N = %d,\tNRHS=%d\n", n, nrhs);
        gflops = calGflops(n, nrhs);
        printf("  nThread:96,\tgflops=%lf\n", gflops);
    }
    // big scale
    for (n = 10000; n <= 40000; n += 5000) {
        //nrhs = rand() % n + 1;  // NRHS=[1,N]
        nrhs = n;
        printf("N = %d,\tNRHS=%d\n", n, nrhs);
        gflops = calGflops(n, nrhs);
        printf("  nThread:96,\tgflops=%lf\n", gflops);
    }*/

    // test 48 threads
    omp_set_num_threads(48);
    // small scale
    for (n = 100; n <= 900; n += 100) {
        // nrhs = rand() % n + 1;  // NRHS=[1,N]
        nrhs = n;
        printf("N = %d,\tNRHS=%d\n", n, nrhs);
        gflops = calGflops(n, nrhs);
        printf("  nThread:48,\tgflops=%lf\n", gflops);
    }
    // middle scale
    for (n = 1000; n <= 9000; n += 1000) {
        // nrhs = rand() % n + 1;  // NRHS=[1,N]
        nrhs = n;
        printf("N = %d,\tNRHS=%d\n", n, nrhs);
        gflops = calGflops(n, nrhs);
        printf("  nThread:48,\tgflops=%lf\n", gflops);
    }
    // big scale
    for (n = 10000; n <= 40000; n += 5000) {
        // nrhs = rand() % n + 1;  // NRHS=[1,N]
        nrhs = n;
        printf("N = %d,\tNRHS=%d\n", n, nrhs);
        gflops = calGflops(n, nrhs);
        printf("  nThread:48,\tgflops=%lf\n", gflops);
    }

    /*
    // test 1 threads
    omp_set_num_threads(1);
    // small scale
    for (n = 100; n <= 900; n += 100) {
        //nrhs = rand() % n + 1;  // NRHS=[1,N]
        nrhs = n;
        printf("N = %d,\tNRHS=%d\n", n, nrhs);
        gflops = calGflops(n, nrhs);
        printf("  nThread:1,\tgflops=%lf\n", gflops);
    }
    // middle scale
    for (n = 1000; n <= 9000; n += 1000) {
        //nrhs = rand() % n + 1;  // NRHS=[1,N]
        nrhs = n;
        printf("N = %d,\tNRHS=%d\n", n, nrhs);
        gflops = calGflops(n, nrhs);
        printf("  nThread:1,\tgflops=%lf\n", gflops);
    }
    // big scale
    for (n = 10000; n <= 40000; n += 5000) {
        //nrhs = rand() % n + 1;  // NRHS=[1,N]
        nrhs = n;
        printf("N = %d,\tNRHS=%d\n", n, nrhs);
        gflops = calGflops(n, nrhs);
        printf("  nThread:1,\tgflops=%lf\n", gflops);
    }*/
}

double calGflops(int N, int M) {
    char uplo = ((rand() % 2) == 1) ? 'L' : 'U';
    dataType *A, *B, *W;
    int *ipiv, info;
    char TRF[] = SYTRF_NAME, TRS[] = SYTRS_NAME;
    struct timeval tvStart, tvEnd;
    struct timezone tzStart, tzEnd;
    double result;
    double opTRF, opTRS;
    int lin0 = 0;
    if (((A = (dataType*)malloc(sizeof(dataType) * N * N)) == NULL) ||
        ((B = (dataType*)malloc(sizeof(dataType) * N * M)) == NULL) ||
        ((W = (dataType*)malloc(sizeof(dataType) * N * N)) == NULL) ||
        ((ipiv = (int*)malloc(sizeof(int) * N)) == NULL)) {
        printf("malloc error!\n");
        return -1;
    }
    _CreatMatrix(uplo, N, M, A, B);
    int lwork = N * 64;
    gettimeofday(&tvStart, &tzStart);
    SYSV_ROOK(&uplo, &N, &M, A, &N, ipiv, B, &N, W, &lwork, &info);
    gettimeofday(&tvEnd, &tzEnd);
    opTRF = _opla_(TRF, &N, &M, &lin0, &lin0, &lin0);
    opTRS = _opla_(TRS, &N, &M, &lin0, &lin0, &lin0);
    result = (double)(opTRF + opTRS) /
             ((double)(tvEnd.tv_sec - tvStart.tv_sec) * (double)1000000000 +
              (double)(tvEnd.tv_usec - tvStart.tv_usec) * (double)1000);

    free(A);
    free(B);
    free(W);
    free(ipiv);
    return result;
}
